package cn.com.dbappsecurity.frame.scanner;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import cn.com.dbappsecurity.frame.annotations.Action;
import cn.com.dbappsecurity.frame.annotations.Controller;

/**
 * controller扫描器
 * @author dhz
 */
public class ControllerScanner extends ClassScanner{

	/**
	 * 从指定的包数组中扫描所有do类及controller方法
	 * @param path
	 */
	public static Map<String,Controllers> scanControllersFromPackges(String[] packageNames)throws Exception{
		Map<String,Controllers> result = new HashMap<String,Controllers>();
		for(String packageName : packageNames){
			Map<String,Controllers> controllers = scanControllersFromPackge(packageName);
			Object key = isContains(result,controllers);
			if(key != null){
				throw new Exception("controller["+key.toString()+"]冲突");
			}
			result.putAll(controllers);
		}
		return result;
	}
	
	/**
	 * 从指定的包中扫描所有do类及controller方法
	 * @param path
	 */
	public static Map<String,Controllers> scanControllersFromPackge(String packageName)throws Exception{
		Map<String,Controllers> result = new HashMap<String,Controllers>();
		List<Class<?>> list = scannerPackge(packageName);
		int count = 0;
		for(Class<?> cls : list){
			if(!cls.isAnnotationPresent(Controller.class)){
				continue;
			}
			//扫描controller
			Controllers controllers = new Controllers();
			Method[] ms = cls.getMethods();
			for(Method m : ms){
				Action a = m.getAnnotation(Action.class);
				if(a != null){
					//如未指定action名称则用方法名
					String value = a.value();
					if(StringUtils.isEmpty(value)){
						value = reName(m.getName());
					}
					controllers.registerMethod(cls,value,m);
				}
			}
			Object clsObj = cls.newInstance();
			//do实例
			controllers.setDoInstance(clsObj);
			Controller _d = (Controller)cls.getAnnotation(Controller.class);
			String value = _d.value();
			if(value.startsWith("/")){
				value = value.substring(1);
			}
			if(value.endsWith("/")){
				value = value.substring(0,value.length()-1);
			}
			if(result.containsKey(value)){
				throw new Exception("controller["+value+"]冲突");
			}
			result.put(value,controllers);
			count++;
		}
		LOG.debug("共扫描到包["+packageName+"]中controller类：" + count + " 个");
		return result;
	}
	
	/*
	 * 将驼峰命名规则的方法名改为用中划线隔开 如:getName => get-name
	 * @param name
	 * @return
	 */
	private static String reName(String name){
		Pattern p = Pattern.compile("[A-Z]");
		Matcher m = p.matcher(name);
		StringBuffer sb = new StringBuffer();
		while(m.find()){
			m.appendReplacement(sb,"-" + m.group().toLowerCase());
		}
		m.appendTail(sb);
		return sb.toString();
	}
	
	/*
	 * 判断第一个map中是否包含第二个map中的任意一个key
	 * @param src
	 * @param sub
	 * @return 返回存在的key，不存在则返回null
	 */
	private static Object isContains(Map<String,Controllers> src,Map<String,Controllers> sub){
		for(Object key : sub.keySet()){
			if(src.containsKey(key)){
				return key;
			}
		}
		return null;
	}

}
